package com.eol.admin.modules.system.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.eol.admin.modules.system.service.dto.PictureQueryCriteria;
import lombok.extern.slf4j.Slf4j;
import com.eol.admin.common.utils.QueryHelp;
import com.eol.admin.modules.system.domain.Picture;
import com.eol.admin.modules.system.repository.PictureRepository;
import com.eol.admin.modules.system.service.PictureService;
import com.eol.common.config.SystemPropertiesConfig;
import com.eol.common.oss.OssUtils;
import com.eol.common.sequence.Sequence;
import com.eol.common.utils.FileUtil;
import com.eol.common.utils.PageUtil;
import com.eol.common.utils.ValidationUtil;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Zheng Jie
 * @date 2018-12-27
 */
@Slf4j
@Service(value = "pictureService")
@CacheConfig(cacheNames = "picture")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class PictureServiceImpl implements PictureService {

    private final PictureRepository pictureRepository;
    @Resource
    private Sequence sequence;

    @Resource
    private OssUtils ossUtils;

    @Resource
    private SystemPropertiesConfig systemPropertiesConfig;


    private static final String SUCCESS = "success";

    private static final String CODE = "code";

    private static final String MSG = "message";

    public PictureServiceImpl(PictureRepository pictureRepository) {
        this.pictureRepository = pictureRepository;
    }

    @Override
    @Cacheable
    public Object queryAll(PictureQueryCriteria criteria, Pageable pageable) {
        return PageUtil.toPage(pictureRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable));
    }

    @Override
    public List<Picture> queryAll(PictureQueryCriteria criteria) {
        return pictureRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder));
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Throwable.class)
    public Picture upload(MultipartFile multipartFile, String username) throws IOException {
        String extensionName = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        String fileRealName = FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) + "." + extensionName;
        String filename = sequence.nextString() + "." + extensionName;
        DateTime dateTime = DateTime.now();
        String url = "";
        if (!systemPropertiesConfig.getAliYunOss().isUseOss()) {
            String time = dateTime.toString("YYYYMMdd");
            String locationFilePath = systemPropertiesConfig.getAliYunOss().getFilesUploadPath() + time + "/";
            File localFile = new File(locationFilePath, filename);
            File localFilePath = new File(locationFilePath);
            if (!localFilePath.exists()) {
                localFilePath.mkdir();
            }
            multipartFile.transferTo(localFile);
            url = systemPropertiesConfig.getAliYunOss().getFilesUploadPathBaseUrl() + time + "/" + filename;
        } else {
            String baseUrl = systemPropertiesConfig.getAliYunOss().getBaseFilePrefix() + dateTime.toString("YYYYMMdd") + "/" + filename;
            ossUtils.uploadFile(baseUrl, multipartFile.getBytes());
            url = systemPropertiesConfig.getAliYunOss().getHost() + baseUrl;
        }
        Picture picture = new Picture();
        //转成实体类
        picture.setFilename(fileRealName);
        picture.setUsername(username);
        picture.setUrl(url);
        pictureRepository.save(picture);
        //删除临时文件
        return picture;
    }

    public JSONObject uploadFiles(MultipartFile multipartFile) throws IOException {
        String extensionName = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        String fileRealName = FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) + "." + extensionName;
        String filename = sequence.nextString() + "." + extensionName;
        DateTime dateTime = DateTime.now();
        String url = "";
        if (!systemPropertiesConfig.getAliYunOss().isUseOss()) {
            String time = dateTime.toString("YYYYMMdd");
            String locationFilePath = systemPropertiesConfig.getAliYunOss().getFilesUploadPath() + time + "/";
            File localFile = new File(locationFilePath, filename);
            File localFilePath = new File(locationFilePath);
            if (!localFilePath.exists()) {
                localFilePath.mkdir();
            }
            multipartFile.transferTo(localFile);
            url = systemPropertiesConfig.getAliYunOss().getFilesUploadPathBaseUrl() + time + "/" + filename;
        } else {
            String baseUrl = systemPropertiesConfig.getAliYunOss().getBaseFilePrefix() + dateTime.toString("YYYYMMdd") + "/" + filename;
            ossUtils.uploadFile(baseUrl, multipartFile.getBytes());
            url = systemPropertiesConfig.getAliYunOss().getHost() + baseUrl;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("url", url);
        jsonObject.put("fileName", fileRealName);
        return jsonObject;
    }

    @Override
    @Cacheable(key = "#p0")
    public Picture findById(Long id) {
        Picture picture = pictureRepository.findById(id).orElseGet(Picture::new);
        ValidationUtil.isNull(picture.getId(), "Picture", "id", id);
        return picture;
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public void delete(Picture picture) {
        try {
            HttpUtil.get(picture.getDelete());
            pictureRepository.delete(picture);
        } catch (Exception e) {
            pictureRepository.delete(picture);
        }
    }

    @Override
    @CacheEvict(allEntries = true)
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            delete(findById(id));
        }
    }

    @Override
    public void download(List<Picture> queryAll, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (Picture picture : queryAll) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("文件名", picture.getFilename());
            map.put("图片地址", picture.getUrl());
            map.put("文件大小", picture.getSize());
            map.put("操作人", picture.getUsername());
            map.put("删除地址", picture.getDelete());
            map.put("创建日期", picture.getCreateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }
}
